package com.onpositive.knowledge.model.value.audits;

import com.onpositive.knowledge.model.values.DescribedValue;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.property.ValueUtils;

public abstract class AbstractAllPropertyAudit extends AuditSourceContainer implements IValueAudit {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public AbstractAllPropertyAudit() {}	

	@Override
	public void perform( IProperty prop, Iterable<Object> objects, AbstractAuditResult auditResult)
	{
		auditResult.propertyId=prop.getId();		
		for (Object o : objects) {
			gatherStat(o, prop,auditResult);
		}
		auditResult.looksApplyable = onStatsCompleted(auditResult);
		for (Object o : objects) {
			processStat(o, prop,auditResult);
		}
	}

	protected abstract boolean onStatsCompleted(AbstractAuditResult pm);

	private void processStat(Object o, IProperty prop, AbstractAuditResult pm)
	{
		Object value = prop.getValue(o);
		if ( value == null )
			return ;

		Iterable<Object> collection = ValueUtils.toCollection(value);

		for (Object s : collection)
		{
			if (!(s instanceof DescribedValue)) {
				s = new DescribedValue(value, null);
			}
			if (isSuspicious(o, (DescribedValue) s, prop,pm)) {
				pm.addAsSuspicious(o);
			}
		}
	}

	protected void gatherStat(Object o, IProperty prop, AbstractAuditResult pm)
	{
		Object value = prop.getValue(o);
		if ( value == null )
			return ;
		
		Iterable<Object> collection = ValueUtils.toCollection(value);

		for (Object s : collection) {
			if (!(s instanceof DescribedValue)) {
				s = new DescribedValue(value, null);
			}
			preprocessValue(o, (DescribedValue) s, prop,pm );
		}
	}

	protected abstract void preprocessValue(Object o, DescribedValue value,
			IProperty prop, AbstractAuditResult pm);

	protected abstract boolean isSuspicious(Object o, DescribedValue value,
			IProperty prop,AbstractAuditResult pm);

}
